
#include<iostream>
#include<cstring>
#include<cassert>
using namespace std;
namespace yxt
{
    class string
    {
    private:
        //确定容量
        size_t _capacity;
        //确定大小
        size_t _size;
        char * _c_pchar;
    public:
        //最常用的就是用常量字符串进行构造
        string(const char * ptr = ""):_capacity(strlen(ptr)),
                                _size(_capacity)
        {
            _c_pchar = new char[_capacity + 1];
            memcpy(_c_pchar,ptr,sizeof(ptr));
        }//但是如果只有这一个构造函数就无法在一些需要默认构造的发挥作用
        //可以用空字符串来进行赋值
        ~string()
        {
            _capacity = 0;
            _size = 0;
            delete []_c_pchar;//在删除数组的动态空间应该在指针的前面增加方括号，进行删除
        }
        //拷贝构造函数，因为默认生成的是只能进行相应的浅拷贝，所以要自己进行手写
        //深拷贝的话就要将相应的内容拷贝进去

        string(const string& n1)
        {
            _size = n1._size;
            _capacity = n1._capacity;
            _c_pchar = new char[_capacity + 1];
            memcpy(_c_pchar,n1._c_pchar,_capacity + 1);
        }
        const char& operator[](int pos)const //需要实现两个，一个用于对象的读取，一个用于正常对象的使用
                                //因为要考虑到效率和修改问题所以要用引用实现
        {
            return _c_pchar[pos];
        }
        char& operator[](int pos)
        {
            return _c_pchar[pos];
        }
        //实现范围for只用实现迭代器就行
        typedef char* iterator;
        typedef char* reverse_iterator;
        iterator begin()
        {
            return _c_pchar;
        }
        iterator end()
        {
            return _c_pchar + _size;
        }
        reverse_iterator rbegin()
        {
            return _c_pchar + _size - 1;
        }
        reverse_iterator rend()
        {
            return _c_pchar;
        }
        void reserve(size_t size)
        {
            char * tmp = new char[size + 1];
            strcpy(tmp,_c_pchar);
            delete[] _c_pchar;
            _c_pchar = tmp;
            _capacity = size;
        }
        void push_back(const char n)
        {
            //先判断是否已经满了
            if(_size == _capacity)
            {
                //进行相应的扩容
                //不如调用库里边的扩容函数进行对应的容量增加
                reserve(_capacity * 2);//并不需要多申请一个只需要在这里边多开辟一个
            }
            _c_pchar[_size] = n;
            _size++;
            //因为原来的“\0”被覆盖了，所以要补充一个
            _c_pchar[_size] = '\0';
        }
        void append(const char * str)
        {
            size_t len = strlen(str);
            if(len + _size > _capacity)
            {
                reserve(len + _size);
            }
            strcat(_c_pchar,str);
            _size += len;

        }
        string& operator+=(const char* str)
        {
            append(str);
            return *this;
        }
        string& operator+=(const char n)
        {
            push_back(n);
            return *this;
        }
        friend ostream& operator<<(ostream& out,yxt::string& s2);
        string& insert(size_t pos,size_t n,char s)
        {
            size_t len = _size + n;
            if(len > _capacity)
            {
                reserve(len);
            }

            //可以先进行拼接然后进行互换
            for(int i = _size ;i < len;i++)
            {
                _c_pchar[i] = s;
            }
            _c_pchar[len] = '\0';
            for(int i = _size - 1;i >= pos;i--)
            {
                std::swap(_c_pchar[i],_c_pchar[i + n]);
            }
            _size += n;
            return *this;
        }
        string& insert(size_t pos,const char * scr)
        {
            size_t n = strlen(scr);
            size_t len = _size + n;

            if(len > _capacity)
            {
                reserve(len);
            }
            for(int i = _size,j = 0;i < len;i++,j++)
            {
                _c_pchar[i] = scr[j];
            }
            _c_pchar[len] = '\0';
            for(int i = _size - 1;i >= pos;i--)//不能从_size开始换因为我们放数据就是从这个地方开始放的，所以我们要从原来数据的最后一个开始放

            {
                std::swap(_c_pchar[i],_c_pchar[i + n]);
            }
            _size += n;
            return *this;

        }
        size_t find(const char * str ,size_t pos = 0)const 
        {
            assert(pos < _size);
            const char * tmp  = strstr(_c_pchar,str);
            if(tmp)
            return tmp - _c_pchar;
            return npos;
        }
        size_t capacity() const
        {
            return _capacity;
        }
        size_t size() const
        {
            return _size;
        }
        char * c_str()
        {
            return _c_pchar;
        }
        bool empty()
        {
            return _size == 0;
        }
        void resize(size_t n,char c = '\0')
        {
            if(n < _capacity)
            {
                if(n > _size)
                memset(_c_pchar + _size, c,n - _size);
                _size = n;
                _c_pchar[_size] = '\0';


            }
            else{
                reserve(n);
                memset(_c_pchar + _size, c,n - _size);
                _size = n;
                _c_pchar[_size] = '\0';

            }
        }
        string& erase(size_t pos = 0,size_t len = npos)
        {
            assert(pos < _size);
            if(len == npos || len + _size > _capacity )
            {
                len = _size - pos;
            }
            size_t st = pos;
            size_t end = pos + len;
            for(int i = pos,j = end;j < _size;i++ ,j++)
            {
                std::swap(_c_pchar[i],_c_pchar[j]);
            }
            _c_pchar[_size - len] = '\0';
            return *this;

        }
        void swap(string& s1,string& s2)
        {
            s1._size = s2._size;
            s1._capacity = s2._capacity;
            s1._c_pchar = s2._c_pchar;
        }
        string& operator=(string s1)
        {
            swap(*this,s1);
        }
        public:
        // size_t npos = -1;//静态对象并不能在类内部给缺省值
        const static size_t npos;//不能修改所以只能const
    };
    const size_t string:: npos = -1;//因为是在外边进行初始化的所以要尊崇类型 和 对应的类限制访问
    ostream& operator<<(ostream& out,yxt::string& s1)
    {
        out << s1._c_pchar << endl;
        return out;
    }
   

}

// int main()
// { //capacity 一般不包含“/0”
//     string s3("kkkkk");
//     string ::reverse_iterator a = s3.rbegin();
//     cout << *a << endl; //rend返回的是“/0
//     cout << s3.size() << endl;
//     cout << s3.capacity() << endl;
//     yxt::string n1("llllllll");
//     auto b = n1.rbegin();
//     for(auto i : n1)
//     {
//         cout << i << endl;
//     }
//     for(auto& i : n1)
//     {
//         i++;
//         cout << i << endl;

//     }
//     //其实范围for的本质就是进行了一定的迭代器替换，诸如
//     //就比如上边的代码可以等效替代为
//     yxt::string::iterator c =n1.begin();
//     while(c != n1.end())
//     {
//         cout << (*c) << endl;
//         c++;
//     }
//     return 0;
// }
int main()
{
    yxt::string n1("22222");
    n1 += "2";
    for(int i = 0;i < 100;i++)
    {
         n1.push_back(i + '0');
    }
    n1.insert(1,"3333");
    n1.insert(1,3,'0');
    cout << n1 <<endl;
    n1.resize(1000);
    yxt::string ll(n1);
    return 0;
}
